package tau.dimes.visualization.servlet;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import tau.dimes.beans.LoginBean;
import tau.dimes.util.XmlHelper;

/**
 * Servlet implementation class TestServlet
 */
public class VisualizationServlet extends HttpServlet implements Servlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public VisualizationServlet() {
        super();        
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 String param = request.getParameter("xmlrequest");
		 
		 if (param == null)
		 {
			 response.getWriter().write("ERROR: request param 'xmlrequest' not found");
			 return;
		 }
		 
		 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		 InputSource is = new InputSource();
		 Map<String, String> attributes = new HashMap<String, String>();
		 
		 try
		{
			DocumentBuilder db = dbf.newDocumentBuilder();
			is.setCharacterStream(new StringReader(param));
			Document doc = db.parse(is);
			
			NodeList nlProvider = doc.getElementsByTagName("Provider");
			String providerName = nlProvider.item(0).getTextContent();
						
			NodeList nlAttributes = doc.getElementsByTagName("Attributes");
			Element nAttributes = (Element)nlAttributes.item(0);
			
			if (nAttributes.hasChildNodes())
				for (int i = 0; i < nAttributes.getChildNodes().getLength(); i++)
				{
					Node nAttribute = nAttributes.getChildNodes().item(i);
					if (Element.class.isAssignableFrom(nAttribute.getClass()))
						attributes.put(nAttribute.getAttributes().getNamedItem("name").getTextContent(), nAttribute.getTextContent());
				}
			
			IProvider provider = ProviderFactory.GetProvider(providerName);
			LoginBean loginBean = (LoginBean) request.getSession().getAttribute("login");
			provider.setServerContext(getServletContext());
			provider.setLoginBean(loginBean);
			Document xmlContent = provider.GetXMLContent(attributes);			
			
			if (xmlContent == null)
			{
				response.getWriter().write("ERROR: failed to retrieve data");
				return;
			}
			
			validateXMLContent(xmlContent);
				
			response.getWriter().write(XmlHelper.getStringFromDoc(xmlContent));
		}
		catch (Exception e)
		{
			response.getWriter().write("ERROR: ");
			e.printStackTrace(response.getWriter());
		}		 
	}
	
	private void validateXMLContent(Document xmlContent) throws SAXException, IOException, ParserConfigurationException
	{
		// build an XSD-aware SchemaFactory
		SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

		// get the custom xsd schema describing the required format for my XML files.
		Schema schemaXSD = schemaFactory.newSchema(
			getServletContext().getResource("/Data/DataRequest.xsd"));

		// Create a Validator capable of validating XML files according to my custom schema.
		Validator validator = schemaXSD.newValidator();

		// parse the XML DOM tree against the stricter XSD schema		
		DOMSource domSource = new DOMSource(xmlContent);
		validator.validate(domSource);
	}
}
